﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Transactions;
using Microsoft.EntityFrameworkCore;
using OL.FrameCore.Application.Module;
using OL.FrameCore.Application.Role.Dto;
using OL.FrameCore.Domain.Entity;
//using OL.FrameCore.Domain.IRepository;
using OL.FrameCore.Infrastructure.UnitOfWork;
using OL.FrameCore.Infrastructure.Utility;
using OL.FrameCore.Repository.EF;

namespace OL.FrameCore.Application.Role
{
    public class RoleService :  IRoleService
    {
        IUnitOfWork _unitOfwork;
        IModuleService _moduleService;
        public RoleService(IUnitOfWork unitOfwork, IModuleService moduleService)
        {
            _unitOfwork = unitOfwork;
            _moduleService = moduleService;
        }

        //public List<RoleDto> GetRoleList(int roleId, string roleName)
        //{
        //    Expression<Func<SysRole, bool>> predicate = p =>
        //    (roleId <= 0 ? true : p.Id == roleId)
        //    && (string.IsNullOrEmpty(roleName) ? true : p.RoleName.Contains(roleName));

        //    //var repositoryRole = _unitOfwork.GetRepository<SysRole>();
        //    //var query = repositoryRole.TableNoTracking.Where(predicate).AsQueryable();
        //    //return repositoryRole.PagingAsync<GetDeptListModel>(query, request.PageIndex, request.PageSize).Result;
        //}
        public PageData<GeRoleListResponse> GetRoleList(GetRoleListRequest request)
        {
            Expression<Func<SysRole, bool>> predicate = p =>
            (request.RoleId.HasValue== false ? true : p.Id == request.RoleId)
            && (string.IsNullOrEmpty(request.RoleName) ? true : p.RoleName.Contains(request.RoleName))
            && p.IsDelete == false;

            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var query = repositoryRole.TableNoTracking.Where(predicate).Select(p => new GeRoleListResponse
            {
                Id = p.Id,
                RoleName = p.RoleName,
                Remark = p.Remark,
                CreateTime = p.CreateTime
            });
            return repositoryRole.PagingAsync<GeRoleListResponse>(query, request.PageIndex, request.PageSize).Result;
        }
        /// <summary>
        /// 获取空角色，用于新建角色
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public GetRoleResponse GetEmptyRole()
        {
            var result = new GetRoleResponse();

            //分配的模块
            var repositoryModule = _unitOfwork.GetRepository<SysModule>();
            var query = from a in repositoryModule.TableNoTracking
                        where a.IsDelete == false
                        select new RoleModuleModel
                        {
                            Id = a.Id,
                            ModuleName = a.ModuleName,
                            ModuleCode = a.ModuleCode,
                            ParentId = a.ParentId,
                            SortIndex = a.SortIndex,
                            IsAssign = false
                        };
            result.RoleModules = query.ToList();

            return result;
        }
        /// <summary>
        /// 获取角色
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public GetRoleResponse GetRole(int id)
        {
            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var model = repositoryRole.TableNoTracking.Where(p => p.Id == id && p.IsDelete == false).SingleOrDefault();
            if (model == null)
                throw new Exception($"未找到角色 id:{id}");

            var result = new GetRoleResponse
            {
                Id = model.Id,
                RoleName = model.RoleName,
                Remark = model.Remark,
            };

            //管理员
            if (result.RoleName == "管理员")
            {
                result.RoleModules = _moduleService.GetAllModuleList().Select(p => new RoleModuleModel
                {
                    Id = p.Id,
                    ModuleName = p.ModuleName,
                    ModuleCode = p.ModuleCode,
                    ParentId = p.ParentId,
                    SortIndex = p.SortIndex,
                    IsAssign = true
                }).ToList();
                return result;
            }

            //分配的模块
            var repositoryModule = _unitOfwork.GetRepository<SysModule>();
            var repositoryRoleModuleMap = _unitOfwork.GetRepository<SysRoleModuleMap>();
            var query = from a in repositoryModule.TableNoTracking
                        join b in repositoryRoleModuleMap.TableNoTracking.Where(p => p.RoleId == id) on a.Id equals b.ModuleId into tmpB
                        from b in tmpB.DefaultIfEmpty()
                        where a.IsDelete == false
                        select new RoleModuleModel
                        {
                            Id = a.Id,
                            ModuleName = a.ModuleName,
                            ModuleCode = a.ModuleCode,
                            ParentId = a.ParentId,
                            SortIndex = a.SortIndex,
                            IsAssign = (b != null)
                        };
            var roleModules = query.ToList();
            var roleModulesNew = query.ToList();
            foreach (var li in roleModulesNew)
            {
                //有子节点，设置IsAssign为false，防止tree重复勾选
                if (roleModules.Any(p => p.ParentId == li.Id))
                {
                    li.IsAssign = false;
                }
            }
            result.RoleModules = roleModulesNew;

            return result;
        }
        /// <summary>
        /// 添加角色
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result AddRole(AddRoleRequest request)
        {
            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var repositoryRoleModuleMap = _unitOfwork.GetRepository<SysRoleModuleMap>();

            if (repositoryRole.TableNoTracking.Any(p => p.RoleName == request.RoleName && p.IsDelete == false))
            {
                return new FailResult("角色名称已存在");
            }

            //开启事务
            using (TransactionScope scope = new TransactionScope())
            {
                //添加角色信息
                var model = new SysRole
                {
                    RoleName = request.RoleName,
                    Remark = request.Remark ?? "",
                    CreateId = request.OpeatorId,
                    CreateTime = DateTime.Now,
                    UpdateId = request.OpeatorId,
                    UpdateTime = DateTime.Now,
                    IsDelete = false
                };
                repositoryRole.Insert(model);
                if (model.Id <= 0)
                    return new FailResult("角色添加失败，请重试");

                //角色分配模块
                foreach (var li in request.AssignModules)
                {
                    repositoryRoleModuleMap.Insert(new SysRoleModuleMap
                    {
                        ModuleId = li,
                        RoleId = model.Id,
                        CreateId = request.OpeatorId,
                        CreateTime = DateTime.Now,
                    });
                }

                //提交事务
                scope.Complete();
            }

            return new SuccessResult();
        }
        /// <summary>
        /// 修改角色
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result UpdateRole(UpdateRoleRequest request)
        {
            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var repositoryRoleModuleMap = _unitOfwork.GetRepository<SysRoleModuleMap>();

            var model = repositoryRole.TableNoTracking.Where(p => p.Id == request.Id && p.IsDelete == false).SingleOrDefault();
            if (model == null)
            {
                return new FailResult("找不到数据，请刷新后重试");
            }

            if (repositoryRole.TableNoTracking.Any(p => p.RoleName == request.RoleName && p.IsDelete == false && p.Id!=model.Id))
            {
                return new FailResult("角色名称已存在");
            }

            //管理员不能修改
            if (repositoryRole.TableNoTracking.Any(p => p.RoleName == "管理员" && p.IsDelete == false && p.Id == request.Id))
            {
                return new FailResult("管理员角色不能修改");
            }

            //开启事务
            using (TransactionScope scope = new TransactionScope())
            {
                //修改角色信息
                model.RoleName = request.RoleName;
                model.Remark = request.Remark ?? "";
                model.UpdateId = request.OpeatorId;
                model.UpdateTime = DateTime.Now;
                repositoryRole.Update(model);

                //删除旧的分配模块
                _unitOfwork.ExecuteSqlCommand($"delete from Sys_RoleModuleMap where RoleId={request.Id}");

                //角色分配模块
                foreach (var li in request.AssignModules)
                {
                    repositoryRoleModuleMap.Insert(new SysRoleModuleMap
                    {
                        ModuleId = li,
                        RoleId = model.Id,
                        CreateId = request.OpeatorId,
                        CreateTime = DateTime.Now,
                    });
                }

                //提交事务
                scope.Complete();
            }

            return new SuccessResult();
        }
        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="id"></param>
        /// <param name="opeatorId"></param>
        /// <returns></returns>
        public Result DeleteRole(int id, int opeatorId)
        {
            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var model = repositoryRole.Table.Where(p => p.Id == id && p.IsDelete == false).SingleOrDefault();
            if (model == null)
            {
                return new FailResult("找不到数据，请刷新后重试");
            }

            //管理员不能删除
            if (repositoryRole.TableNoTracking.Any(p => p.RoleName == "管理员" && p.IsDelete == false && p.Id == id))
            {
                return new FailResult("管理员角色不能删除");
            }

            model.IsDelete = true;
            model.UpdateId = opeatorId;
            model.UpdateTime = DateTime.Now;
            _unitOfwork.Save();

            return new SuccessResult();
        }

        public List<RoleModuleModel> GetRoleModule(int roleId)
        {
            var repositoryModule = _unitOfwork.GetRepository<SysModule>();
            var repositoryRoleModuleMap = _unitOfwork.GetRepository<SysRoleModuleMap>();

            var query = from a in repositoryModule.TableNoTracking
                        join b in repositoryRoleModuleMap.TableNoTracking on a.Id equals b.ModuleId into tmpB
                        from b in tmpB.DefaultIfEmpty()
                        where b.RoleId == roleId
                        select new RoleModuleModel
                        {
                            Id = a.Id,
                            ModuleName = a.ModuleName,
                            ModuleCode = a.ModuleCode,
                            ParentId = a.ParentId,
                            SortIndex = a.SortIndex,
                            IsAssign = b == null
                        };
            return query.ToList();
        }
    }
}
